package com.bzkj.basicinfo.service.impl.ncc;

import cn.hutool.core.collection.CollectionUtil;
import com.bzkj.basicinfo.domain.basic.vo.*;
import com.bzkj.basicinfo.domain.ncc.NccBasicSkuInfo;
import com.bzkj.basicinfo.domain.ncc.TableXXXSku;
import com.bzkj.basicinfo.domain.wms.WmsStoStockEntity;
import com.bzkj.basicinfo.domain.wms.vo.TableXXXSkuVo;
import com.bzkj.basicinfo.mapper.NccBasicSkuInfoMapper;
import com.bzkj.basicinfo.mapper.TableXXXSkuMapper;
import com.bzkj.basicinfo.mapper.WarehouseMapper;
import com.bzkj.basicinfo.mapper.WmsStoStockMapper;
import com.bzkj.basicinfo.service.ncc.NccBasicSkuInfoService;
import com.bzkj.basicinfo.service.ncc.TableXXXSkuService;
import com.bzkj.basicinfo.utils.GenerateQRCodeUtils;
import com.bzkj.common.core.domain.AjaxResult;
import com.bzkj.common.core.domain.R;
import com.bzkj.common.core.domain.model.LoginUser;
import com.bzkj.common.utils.DateUtils;
import com.bzkj.common.utils.SecurityUtils;
import com.bzkj.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wl
 * @description 针对表【table_1001ZZ100000000FAUD9_sku】的数据库操作Service实现
 * @createDate 2024-12-23 09:12:49
 */
@Slf4j
@Service
public class TableXXXSkuServiceImpl implements TableXXXSkuService {

    @Autowired
    private TableXXXSkuMapper tableXXXSkuMapper;

    @Autowired
    private NccBasicSkuInfoMapper nccBasicSkuInfoMapper;

    @Autowired
    private GenerateQRCodeUtils gqrc;

    @Autowired
    private NccBasicSkuInfoService nccBasicSkuInfoService;

    @Autowired
    private WmsStoStockMapper wmsStoStockMapper;

    @Autowired
    private WarehouseMapper warehouseMapper;

    private static Integer maxNum = 2000;

    private static final String NA_VALUE = "N/A";
    private static final String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 新增动态表数据
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertTableXXXSkuData(TableXXXSku entity) {
        String tableName = "table_" + entity.getPkMarbasclass() + "_sku";
        //        if(! tableXXXSkuMapper.isTableExist(tableName)) return AjaxResult.error("该表不存在");
        try {
            // 批量新增数据
            Map<String, Object> map = extracted(entity, tableName);
            List<TableXXXSku> xxxSkus = (List<TableXXXSku>) map.get("data");
            nccBasicSkuInfoMapper.updateNccBasicSkuInfoDef5(entity.getPkMarbasclass(), (Integer) map.get("num"));
            //参数为21个，每次截取50条数据。sqlserver批量插入参数个数最大限度为2100
            if (!xxxSkus.isEmpty()) {
                for (int i = 0; i < xxxSkus.size(); i += 50) {
                    int endIndex = Math.min(i + 50, xxxSkus.size());
                    List<TableXXXSku> xxxSkus1 = xxxSkus.subList(i, endIndex);
                    tableXXXSkuMapper.batchInsertData(xxxSkus1, tableName);
                }
            }
            if (entity.getFlag()) {
                List<TableXXXSkuVo1> vos = gqrc.crateQRCode(xxxSkus, entity.getPkMarbasclass(), entity.getVbatchCode());
                return AjaxResult.success("批量新增数据，并生成二维码成功", vos);
            }
            return AjaxResult.success("批量新增数据成功");
        } catch (Exception e) {
            log.error("批量新增数据失败:{}", e);
            return AjaxResult.error("批量新增数据失败");
        }
    }

    /**
     * 根据条件查询数据，创建二维码
     *
     * @param entity
     * @return
     */
    //    public AjaxResult createQrCodeN(TableXXXSku entity)
    //    {
    //        try {
    //            List<Map<String, Object>> list = tableXXXSkuMapper.findTableXXXSkuList(entity, "table_" + entity.getPkMarbasclass() + "_sku");
    //
    //            if(! list.isEmpty()) gqrc.crateQRCodeMap(list, entity.getPkMarbasclass());
    //            return AjaxResult.success(list);
    //        } catch(Exception e) {
    //            log.error("操作失败:{}", e);
    //            return AjaxResult.error("操作失败");
    //        }
    //    }
    //
    public AjaxResult findTableXXXSkuList(String pkMarbasclass, String pkBatchcode, String cwarehouseId, String cproductId) {
        Map<String, Object> map = new HashMap<>();
        String tableName = "table_" + pkMarbasclass + "_sku";
        if (tableXXXSkuMapper.isTableExist(tableName)) {
            List<TableXXXSku> list = tableXXXSkuMapper.findTableXXXSkuListByBatchCode(tableName, pkBatchcode, null);
            List<TableXXXSkuVo> vos = new CopyOnWriteArrayList<>();
            Map<String, TableXXXSkuVo> collect = list.parallelStream().map(item -> {
                TableXXXSkuVo temp = new TableXXXSkuVo();
                BeanUtils.copyProperties(item, temp);
                if (item.getSkuParentId().equals("0")) vos.add(temp);
                return temp;
            }).collect(Collectors.toMap(TableXXXSkuVo::getSkuBarId, Function.identity()));

            list.parallelStream().forEach(item -> {
                TableXXXSkuVo vo = collect.get(item.getSkuParentId());
                if (!Objects.isNull(vo)) {
                    TableXXXSkuVo temp = new TableXXXSkuVo();
                    BeanUtils.copyProperties(item, temp);
                    vo.getChildren().add(temp);
                }
            });
            map.put("vos", vos);
        }
        //根据物料主键和批号获取物料数据
        WmsStoStockEntity stoStockEntity = wmsStoStockMapper.finWmsStoStockOne(pkMarbasclass, pkBatchcode, cwarehouseId, cproductId);
        //判断不同状态下是否有数据，有数据时输出状态列表
        //获取单据状态
        List<Map<String, Object>> stateList = new ArrayList<>();
        if (Objects.nonNull(stoStockEntity)) {
            //合格数量
            if (stoStockEntity.getQualifiedNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m3 = new HashMap<>();
                m3.put("PK_STORESTATE", "1001A110000000002T09");
                m3.put("name", "合格");
                m3.put("num", stoStockEntity.getQualifiedNum());
                stateList.add(m3);
            }
            //不合格数量
            if (stoStockEntity.getUnqualifiedNum() .compareTo(BigDecimal.ZERO)!= 0) {
                HashMap<String, Object> m1 = new HashMap<>();
                m1.put("PK_STORESTATE", "1001ZZ1000000002XCX4");
                m1.put("name", "不合格");
                m1.put("num", stoStockEntity.getUnqualifiedNum());
                stateList.add(m1);
            }
            //待验数量
            if (stoStockEntity.getQuarantineNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m2 = new HashMap<>();
                m2.put("PK_STORESTATE", "1001A110000000002T08");
                m2.put("name", "待检");
                m2.put("num", stoStockEntity.getQuarantineNum());
                stateList.add(m2);
            }
            if (stoStockEntity.getLimitEligibilityNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m4 = new HashMap<>();
                m4.put("PK_STORESTATE", "1001B1100000008N4LKD");
                m4.put("name", "限制合格");
                m4.put("num", stoStockEntity.getLimitEligibilityNum());
                stateList.add(m4);
            }
            if (stoStockEntity.getResearchNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m4 = new HashMap<>();
                m4.put("PK_STORESTATE", "1001B110000000FNCCLS");//研究用  生产环境pk:1001B110000000FNCCLS
                m4.put("name", "研究用");
                m4.put("num", stoStockEntity.getResearchNum());
                stateList.add(m4);
            }
            if (stoStockEntity.getPendingNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m4 = new HashMap<>();
                m4.put("PK_STORESTATE", "1001B1100000008HXPEP");
                m4.put("name", "待处理");
                m4.put("num", stoStockEntity.getPendingNum());
                stateList.add(m4);
            }
            if (stoStockEntity.getQualifiedNoUseNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m4 = new HashMap<>();
                m4.put("PK_STORESTATE", "1001B110000000CMZGQ2");//合格不予上市  生产环境pk:1001B110000000CMZGQ2
                m4.put("name", "合格不予上市");
                m4.put("num", stoStockEntity.getQualifiedNoUseNum());
                stateList.add(m4);
            }
            if (stoStockEntity.getSkuNoStateNum().compareTo(BigDecimal.ZERO) != 0) {
                HashMap<String, Object> m4 = new HashMap<>();
                m4.put("PK_STORESTATE", "");
                m4.put("name", "无库存状态");
                m4.put("num", stoStockEntity.getSkuNoStateNum());
                stateList.add(m4);
            }

            map.put("status", stateList);//带出单据状态
        }
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult findPrintedSkuInfo(String pkMaterial, String pkBatchcode, String row, String level) {
        Map<String, Object> map = new HashMap<>();
        String tableName = "table_" + pkMaterial + "_sku";
        if (tableXXXSkuMapper.isTableExist(tableName)) {
            List<TableXXXSkuVo> vos = new CopyOnWriteArrayList<>();
            List<TableXXXSku> list = tableXXXSkuMapper.findTableXXXSkuListByBatchCode(tableName, pkBatchcode, row);
            List<TableXXXSku> filterList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(list)) {
                //打印级别
                if (level.equals("1")) {
                    filterList = list.stream().filter(i -> i.getSkuParentId().equals("0") && i.getSkuPkgratio().equals("1")).collect(Collectors.toList());
                } else {
                    filterList = list.stream().filter(i -> !i.getSkuPkgratio().equals("1")).collect(Collectors.toList());
                }
            }
            Map<String, TableXXXSkuVo> collect = filterList.stream().map(item -> {
                TableXXXSkuVo temp = new TableXXXSkuVo();
                BeanUtils.copyProperties(item, temp);
                if (item.getSkuParentId().equals("0")) vos.add(temp);
                return temp;
            }).collect(Collectors.toMap(TableXXXSkuVo::getSkuBarId, Function.identity()));

            filterList.parallelStream().forEach(item -> {
                TableXXXSkuVo vo = collect.get(item.getSkuParentId());
                if (!Objects.isNull(vo)) {
                    TableXXXSkuVo temp = new TableXXXSkuVo();
                    BeanUtils.copyProperties(item, temp);
                    vo.getChildren().add(temp);
                }
            });
            //排序处理
            if (CollectionUtil.isNotEmpty(vos)) {
                vos.forEach(item -> {
                    List<TableXXXSkuVo> children = item.getChildren();
                    if (CollectionUtil.isNotEmpty(children)) {
                        children.sort(Comparator.comparing(TableXXXSkuVo::getSkuBarId));
                    }
                });
                vos.sort(Comparator.comparing(TableXXXSkuVo::getSkuBarId));
            }
            map.put("vos", vos);
        }
        return AjaxResult.success(map);
    }

    /**
     * 打印sku信息
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R printSkuInfo(PrintSkuInfoVo vo) {
        try {
            /**
             * 各类校验逻辑
             */
            // 初始化变量
            List<TableXXXSku> qrList = new ArrayList<>(); // 存储需要生成二维码的数据
//            BigDecimal number = vo.getNumber();//总数量
            Integer printNumber = vo.getPrintNumber();// 打印数量
            //是否可超数打印
            if(!handleOverMax(vo)){
                return R.fail("不可超数量打印，请重新打印");
            }
            // 根据物料ID生成动态表名
            String tableName = "table_" + vo.getPkMaterial() + "_sku";
            // 获取物料规格信息
            NccBasicSkuInfo nccBasicSku = nccBasicSkuInfoMapper.getNccBasicSkuINfoOneByPkMarbasclass(vo.getPkMaterial());
            if (Objects.nonNull(nccBasicSku)) {
                vo.setMaterialspec(nccBasicSku.getMaterialspec());
            }
            //判断批号是否存在
            if (StringUtils.isBlank(vo.getVbatchCode())) {
                return R.ok(handleNonOneCode(vo));
            }
            // 判断动态表是否存在
            if (tableXXXSkuMapper.isTableExist(tableName)) {
                //重打直接清空数据不进行输出
                if (vo.getPrintMode().equals("1")) {
                    LoginUser loginUser = SecurityUtils.getLoginUser();
                    String username = loginUser.getUsername();
                    //获取单据号，根据单据号来判断单据状态
                    String vbillcode = vo.getVbillcode().trim();
                    String substring = vbillcode.substring(0, 2);
                    //期初打印直接清空
                    if(substring.equals("QC")){
                        tableXXXSkuMapper.deleteBeforeTableData(tableName, substring, vo.getVbatchCode(), vo.getRow());
                        return R.ok("清空成功，请重新打印");
                    }
                    //管理员删除时根据批号进行删除
                    if(username.equals("admin")){
                        tableXXXSkuMapper.deleteTableDataByVbatchCode(tableName,vo.getVbatchCode());
                        return R.ok("清空成功，请重新打印");
                    }else{
                        WmsStoStockEntity stoStockEntity;
                        switch (substring) {
                            case "CR": //采购入
                                stoStockEntity = wmsStoStockMapper.findWmsInDetailMaterial(vo);
                                break;
                            case "TR"://其他入
                                stoStockEntity = wmsStoStockMapper.findWmsInDetailOther(vo);
                                break;
                            case "CC"://材料出
                                stoStockEntity = wmsStoStockMapper.findWmsOutMaterial(vo);
                                break;
                            case "TC"://其他出
                                stoStockEntity = wmsStoStockMapper.findWmsOutDetailOther(vo);
                                break;
                            case "ZK"://转库
                                stoStockEntity = wmsStoStockMapper.findWmsMoveDetailOrder(vo);
                                break;
                            case "PR"://成品入
                                stoStockEntity = wmsStoStockMapper.findWmsProductDetailOrder(vo);
                                break;
                            default:
                                stoStockEntity = new WmsStoStockEntity();
                                break;
                        }
                        if (StringUtils.isNotBlank(stoStockEntity.getSkuState()) && (stoStockEntity.getSkuState().equals("0")
                                || stoStockEntity.getSkuState().equals("1") || stoStockEntity.getSkuState().equals("2"))) {
                            tableXXXSkuMapper.deleteTableData(tableName, vbillcode, vo.getVbatchCode(), vo.getRow());
                            return R.ok("清空成功，请重新打印");
                        } else {
                            return R.fail("清空失败，此单据已存在业务数据，不可清空");
                        }
                    }
                }
                // 查询表中已有的数据
                List<TableXXXSku> list = tableXXXSkuMapper.findListData(tableName, vo.getVbillcode(), vo.getBatchCode(), vo.getRow());
                //根据行号筛选数据
                List<TableXXXSku> xxxSkus = list.stream().filter(i -> i.getRow().equals(vo.getRow())).collect(Collectors.toList());
                if (xxxSkus.isEmpty()) {
                    // 如果表为空，处理新数据
                    return handleEmptyTable(vo, tableName, printNumber, qrList);
                } else {
                    // 如果表不为空，处理已有数据
                    return handleNonEmptyTable(vo, tableName, list, printNumber, qrList);
                }
            } else {
                //重打直接清空数据不进行输出
                if (vo.getPrintMode().equals("1")) {
                    return R.ok("清空成功，请重新打印");
                }
                // 如果表不存在，创建表并处理新数据
                return handleNewTable(vo, tableName, printNumber, qrList);
            }
        } catch (Exception e) {
            // 捕获异常并记录日志
            log.error("操作失败: {}", e.getMessage(), e);
            return R.fail("操作失败");
        }
    }

    @Override
    public AjaxResult repairPrintSkuInfo(PrintSkuInfoVo vo) {
        String tableName = "table_" + vo.getPkMaterial() + "_sku";
        if (tableXXXSkuMapper.isTableExist(tableName)) {
            String sortNum = vo.getSortNum();
            //批量打印时进行分割
            String[] split = sortNum.split("-");
            String startSortNum = split[0];
            String endSortNum = null;
            if (split.length > 1) {
                endSortNum = split[1];
            }
            List<TableXXXSku> infoBySortNum;
            Integer endSortNum1 = endSortNum == null ? null : Integer.valueOf(endSortNum);
            if (vo.getBeforePrintFlag().equals("1")) {
                //增加判断是否是期初打印
                String vbillcode = vo.getVbillcode().trim();
                String substring = vbillcode.substring(0, 2);
                List<TableXXXSku> beforeInfoBySortNum;
                if(Objects.nonNull(endSortNum1)){
                     beforeInfoBySortNum = tableXXXSkuMapper.findBeforeInfoBySortNum(tableName, substring, Integer.valueOf(startSortNum),
                            endSortNum1, null, "0");
                }else{
                    beforeInfoBySortNum = tableXXXSkuMapper.findBeforeInfoBySortNum1(tableName, substring, startSortNum,
                             null, "0");
                }
                if (endSortNum != null && vo.getLevel().equals("2")) {
                    infoBySortNum = beforeInfoBySortNum.stream().filter(i -> !i.getCodeLevel().equals("2")).collect(Collectors.toList());
                } else {
                    infoBySortNum = beforeInfoBySortNum;
                }
            } else {
                infoBySortNum = tableXXXSkuMapper.findInfoBySortNum(tableName, vo.getVbillcode(), Integer.valueOf(startSortNum),
                        endSortNum1,  null);
            }
            if (CollectionUtil.isNotEmpty(infoBySortNum)) {
                List<TableXXXSku> collect;
                if (StringUtils.isBlank(vo.getLevel())) {
                    collect = infoBySortNum;
                } else {
                    if (vo.getLevel().equals("1")) {
                        collect = infoBySortNum.stream().filter(i -> i.getSkuPkgratio().equals("1") && i.getRow().equals(vo.getRow())).collect(Collectors.toList());
                    } else {
                        collect = infoBySortNum.stream().filter(i -> !i.getSkuPkgratio().equals("1") && i.getRow().equals(vo.getRow())).collect(Collectors.toList());
                        //根据小码的parentId获取大码数据
                        List<TableXXXSku> qcParentCodeList = this.getQcParentCodeList(collect, tableName, "QC");
                        collect.addAll(qcParentCodeList);
                    }
                }
                Map<String, Object> map = new HashMap<>();
                List<TableXXXSkuVo1> vos = gqrc.crateQRCode(collect, vo.getPkMaterial(), vo.getVbatchCode());
                List<PrintSkuInfoVo> printSkuInfoVos = dataAssembly(new ArrayList<>(), vos, vo);
                printSkuInfoVos.forEach(i->i.setMaterialspec(collect.get(0).getMaterialspec()));
                map.put("printData",printSkuInfoVos);
                map.put("vo", vo);
                return AjaxResult.success(map);
            } else {
                if (StringUtils.isBlank(vo.getSortNum())) {
                    return AjaxResult.error("当前单据无数据");
                } else {
                    return AjaxResult.error("当前单据下没有容器号为" + vo.getSortNum() + "的数据");
                }
            }
        } else {
            return AjaxResult.error("当前单据无数据");
        }
    }
    @Override
    public R batchPrintNoOneCode(List<PrintNoOneCodeSkuInfoVo> list) {
        Map<String, Object> map = new HashMap<>();
        List<PrintSkuInfoVo> skuInfoVos = new ArrayList<>();
        //批量处理数据
        list.forEach(vo->{
            PrintSkuInfoVo infoVo = new PrintSkuInfoVo();
            TableXXXSku xxxSku = new TableXXXSku();
            infoVo.setExpirationDate(vo.getDvalidate());
            infoVo.setResetDate(vo.getDbizdate());
            infoVo.setPkMaterial(vo.getCmaterialoid().getPk());
            infoVo.setSkuName(vo.getCmaterialoid().getName());
            infoVo.setSupplierCode(vo.getVbcdef2());
            infoVo.setFinallyCode(vo.getFinallyCode());
            if(StringUtils.isNotBlank(vo.getVbatchcode())){
                infoVo.setVbatchCode(vo.getVbatchcode());
                xxxSku.setVbatchCode(vo.getVbatchcode());
            }
            infoVo.setSkuUnit(vo.getCastunitid().getName());
            infoVo.setMaterialspec(vo.getMaterialtype());
            xxxSku.setPeriodValidity(DateUtils.parseDate(vo.getDvalidate()));
            xxxSku.setResetDate(DateUtils.parseDate(vo.getDbizdate()));
            xxxSku.setFinallyCode(vo.getFinallyCode());
            String graphid = null;
            //gmp码不同取值来源
            if(Objects.isNull(vo.getGraphid())){
                if(Objects.nonNull(vo.getAdditionMap())){
                     graphid = vo.getAdditionMap().get("graphid").toString();
                }
            }else{
                graphid = vo.getGraphid();
            }
            infoVo.setGraphid(graphid);
            xxxSku.setGraphid(graphid);
            gqrc.crateQRCode(xxxSku, vo.getCmaterialoid().getPk());
            List<PrintSkuInfoVo> printSkuInfoVos = dataAssembly(Collections.singletonList(xxxSku), new ArrayList<>(), infoVo);
            printSkuInfoVos.forEach(i -> {
                if (Objects.nonNull(i.getResetDate()) && i.getResetDate().equals("1900-01-01")) {
                    i.setResetDate("N/A");
                }
            });
            skuInfoVos.addAll(printSkuInfoVos);
        });
        map.put("printData", skuInfoVos);
        return R.ok(map);
    }
    /**
     * 处理表为空的情况
     */
    private R handleEmptyTable(PrintSkuInfoVo vo, String tableName, Integer printNumber, List<TableXXXSku> qrList) {
        if (vo.getIsOneCode()) {
            // 创建一物一码
            return handleOneCode(vo, tableName, printNumber, qrList);
        }
        return R.ok(handleNonOneCode(vo));
    }

    private R handleOneCode(PrintSkuInfoVo vo, String tableName, Integer printNumber, List<TableXXXSku> qrList) {
        Map<String, Object> map = new HashMap<>();
        // 创建一物一码
        List<TableXXXSkuVo1> vos;
        if (vo.getLevel().equals("1")) {
            // 处理一级码
            vos = handleLevelOne(vo, tableName, printNumber, qrList);
        } else {
            // 处理二级码
            vos = handleLevelTwo(vo, tableName, printNumber, qrList);
        }

        map.put("printData", dataAssembly(new ArrayList<>(), vos, vo));
        map.put("vo", vo);
        return R.ok(map);
    }

    /**
     * 是否超量打印处理
     * @param vo
     * @return
     */
    private boolean handleOverMax(PrintSkuInfoVo vo) {
        if (vo.getOverMax() == 0 && !vo.getPrintMode().equals("1") && !vo.getPrintMode().equals("2")) {
            double zeroSum = 0;
            String skuNnum = vo.getSkuNnum();//最小使用数量
            int printNumber = Objects.isNull(vo.getPrintNumber()) ? 1 : vo.getPrintNumber();
            double num = Double.parseDouble(skuNnum) * printNumber;//打印总数
            double printedNum = Double.parseDouble(Objects.isNull(vo.getTotalSkuNum())? String.valueOf(0) :vo.getTotalSkuNum());//已打印数量
            //判断零箱数量
            if (CollectionUtil.isNotEmpty(vo.getZeroPrintList())) {
                zeroSum = vo.getZeroPrintList().stream().mapToDouble(item -> Double.parseDouble(item.getSkuNnum())).sum();
            }
            double total = zeroSum + num + printedNum;
            int compareTo = vo.getNumber().compareTo(BigDecimal.valueOf(total));
            if (compareTo < 0) {
                return false;
            }
        }
        return true;
    }
    /**
     * 不创建一物一码逻辑处理
     *
     * @param vo 打印入参对象
     * @return
     */
    private Map<String, Object> handleNonOneCode(PrintSkuInfoVo vo) {
        Map<String, Object> map = new HashMap<>();
        TableXXXSku xxxSku = getTableXXXSku(vo, null);
        gqrc.crateQRCode(xxxSku, vo.getPkMaterial());
        List<PrintSkuInfoVo> printSkuInfoVos = dataAssembly(Arrays.asList(xxxSku), new ArrayList<>(), vo);
        printSkuInfoVos.forEach(i->{
            if (i.getResetDate().equals("1900-01-01")){
                i.setResetDate("N/A");
            }
        });
        map.put("printData", printSkuInfoVos);
        map.put("vo", vo);
        return map;
    }

    /**
     * 处理表不为空的情况
     */
    private R handleNonEmptyTable(PrintSkuInfoVo vo, String tableName, List<TableXXXSku> list,
                                  Integer printNumber, List<TableXXXSku> qrList) {
        Map<String, Object> map = new HashMap<>();
        //不创建一物一码
        if (!vo.getIsOneCode()) {
            map.putAll(handleNonOneCode(vo));
        } else {
            // 创建一物一码
            List<TableXXXSkuVo1> vos;
            if (vo.getLevel().equals("1")) {
                // 处理一级码
                vos = handleLevelOne(vo, tableName, printNumber, qrList);
            } else {
                // 处理二级码
                vos = handleLevelTwo(vo, tableName, printNumber, qrList);
            }

            map.put("printData", dataAssembly(new ArrayList<>(), vos, vo));
            map.put("vo", vo);
        }
        return R.ok(map);
    }

    /**
     * 处理一级码数据
     *
     * @param vo
     * @param tableName   表名
     * @param printNumber 打印数量
     * @param qrList      创建二维码的列表
     * @return
     */
    private List<TableXXXSkuVo1> handleLevelOne(PrintSkuInfoVo vo, String tableName,
                                                Integer printNumber, List<TableXXXSku> qrList) {
        List<TableXXXSku> list = new ArrayList<>();
        if (!vo.getPrintMode().equals("2")) {
            list = handleInsertTableData(vo, tableName);
        }
        // 根据打印模式处理数据
        return handlePrintMode(vo, tableName, list, printNumber, qrList);
    }

    /**
     * 处理二级码
     */
    private List<TableXXXSkuVo1> handleLevelTwo(PrintSkuInfoVo vo, String tableName,
                                                Integer printNumber, List<TableXXXSku> qrList) {
        List<TableXXXSku> list = new ArrayList<>();
        if (!vo.getPrintMode().equals("2")) {
            list = handleInsertTableData(vo, tableName);
        }
        // 根据打印模式处理数据
        return handlePrintMode(vo, tableName, list, printNumber, qrList);
    }

    /**
     * 处理打印模式（续打或补打）
     */
    private List<TableXXXSkuVo1> handlePrintMode(PrintSkuInfoVo vo, String tableName, List<TableXXXSku> dataList,
                                                 Integer printNumber, List<TableXXXSku> qrList) {
        if (vo.getPrintMode().equals("0")) {
            // 续打
            return handleContinuePrint(vo, tableName, dataList, printNumber, qrList);
        } else {
            //补打
            return handleRePrint(vo, tableName, dataList, printNumber, qrList);
        }
    }

    /**
     * 续打逻辑
     */
    private List<TableXXXSkuVo1> handleContinuePrint(PrintSkuInfoVo vo, String tableName, List<TableXXXSku> list,
                                                     Integer printNumber, List<TableXXXSku> qrList) {
        List<TableXXXSku> tableXXXSkus = new ArrayList<>();
        //增加零箱判断
        if(CollectionUtil.isNotEmpty(vo.getZeroPrintList())){
            int size = vo.getZeroPrintList().size();
            int total = vo.getPrintNumber() + size;
            vo.setPrintNumber(total);
            printNumber = total;
        }
        if (CollectionUtil.isNotEmpty(list)) {
            if (vo.getLevel().equals("1")) {
                tableXXXSkus = list.stream().filter(i -> i.getSkuParentId().equals("0") && i.getSkuPkgratio().equals("1"))
                        .sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).limit(printNumber).collect(Collectors.toList());
            } else {
                List<TableXXXSku> smallCodeList = new ArrayList<>();
                //二级数据处理
                if (StringUtils.isNotBlank(vo.getSortNum())) {
                    smallCodeList = list.stream().filter(i -> i.getCodeLevel().equals("1")
                                    && !i.getSkuPkgratio().equals("1") &&
                                    Integer.parseInt(i.getSortNum()) > Integer.parseInt(vo.getSortNum()))
                            .sorted(Comparator.comparing(TableXXXSku::getSkuBarId)).limit(vo.getPrintNumber())
                            .collect(Collectors.toList());
                } else {
                    smallCodeList = list.stream().filter(i -> i.getCodeLevel().equals("1")
                                    && !i.getSkuPkgratio().equals("1"))
                            .sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).limit(vo.getPrintNumber())
                            .collect(Collectors.toList());
                }
                //获取小码数据
                tableXXXSkus.addAll(smallCodeList);
                //获取大码数据
                tableXXXSkus.addAll(getParentCodeList(smallCodeList, tableName, vo.getVbillcode()));
                List<TableXXXSku> removeList = tableXXXSkus.stream().filter(i -> !i.getSkuPkgratio().equals("1:" + vo.getPackagingRatio())).collect(Collectors.toList());
                tableXXXSkus.removeAll(removeList);
                CollectionUtil.distinct(tableXXXSkus);
            }
        }
        qrList.addAll(tableXXXSkus);
        return gqrc.crateQRCode(qrList, vo.getPkMaterial(), vo.getVbatchCode());
    }

    /**
     * 补打逻辑
     */
    private List<TableXXXSkuVo1> handleRePrint(PrintSkuInfoVo vo, String tableName, List<TableXXXSku> dataList,
                                               Integer printNumber, List<TableXXXSku> qrList) {
        List<TableXXXSku> collect = new ArrayList<>();
        dataList = tableXXXSkuMapper.findListData(tableName, vo.getVbillcode(), vo.getBatchCode(), null);
        String sortNum = vo.getSortNum();
        //批量打印时进行分割
        String[] split = sortNum.split("-");
        String startSortNum = split[0];
        String endSortNum = null;
        if (split.length > 1) {
            endSortNum = split[1];
        }
        //一级数据处理
        if (vo.getLevel().equals("1")) {
            //一级补打逻辑
            if (StringUtils.isNotBlank(endSortNum)) {
                String finalEndSortNum = endSortNum;
                collect = dataList.stream().filter(i -> Integer.parseInt(i.getSortNum()) >= Integer.parseInt(startSortNum) &&
                                Integer.parseInt(i.getSortNum()) <= Integer.parseInt(finalEndSortNum))
                        .collect(Collectors.toList());
            } else {
                collect = dataList.stream().filter(i -> i.getSortNum().equals(startSortNum))
                        .collect(Collectors.toList());
            }
        } else {
            //二级数据处理
            //获取小码数据
            List<TableXXXSku> smallCodeList;
            if (StringUtils.isNotBlank(endSortNum)) {
                String finalEndSortNum = endSortNum;
                smallCodeList = dataList.stream().filter(i -> i.getCodeLevel().equals("1")
                                && !i.getSkuPkgratio().equals("1") && Integer.parseInt(i.getSortNum()) >= Integer.parseInt(startSortNum) &&
                                Integer.parseInt(i.getSortNum()) <= Integer.parseInt(finalEndSortNum))
                        .collect(Collectors.toList());
            } else {
                smallCodeList = dataList.stream().filter(i -> i.getCodeLevel().equals("1")
                                && !i.getSkuPkgratio().equals("1") && i.getSortNum().equals(vo.getSortNum()))
                        .collect(Collectors.toList());
            }
            collect.addAll(smallCodeList);
            //获取大码数据
            collect.addAll(getParentCodeList(smallCodeList, tableName, vo.getVbillcode()));
        }
        qrList.addAll(collect);
        return gqrc.crateQRCode(qrList, vo.getPkMaterial(), vo.getVbatchCode());
    }

    /**
     * 更新打印标识
     */
    private void updatePrintFlag(String tableName, List<TableXXXSku> updateList, int flag) {
        if (CollectionUtil.isNotEmpty(updateList)) {
            List<Integer> idList = updateList.stream().map(TableXXXSku::getId).collect(Collectors.toList());
            tableXXXSkuMapper.updateXXXSkuPrintFlag(idList, tableName, flag);
        }
    }

    /**
     * 处理新表的情况
     *
     * @param vo
     * @param tableName   表名
     * @param printNumber 打印数量
     * @return
     */
    private R handleNewTable(PrintSkuInfoVo vo, String tableName, Integer printNumber, List<TableXXXSku> qrList) {
        //创建一物一码
        if (vo.getIsOneCode()) {
            // 创建商品动态表
            nccBasicSkuInfoService.nccBasicSkuInfoCreateTableXXXSku(vo.getPkMaterial());
            // 创建一物一码
            List<TableXXXSkuVo1> vos;
            if (vo.getLevel().equals("1")) {
                // 处理一级码
                vos = handleLevelOne(vo, tableName, printNumber, qrList);
            } else {
                // 处理二级码
                vos = handleLevelTwo(vo, tableName, printNumber, qrList);
            }
            // 组装返回结果
            Map<String, Object> map = new HashMap<>();
            map.put("printData", dataAssembly(new ArrayList<>(), vos, vo));
            map.put("vo", vo);
            return R.ok(map);
        } else {
            // 不创建一物一码
            return R.ok(handleNonOneCode(vo));
        }
    }

    /**
     * 根据parentId获取父码数据
     *
     * @param xxxSkus
     * @param tableName
     * @return
     */
    private List<TableXXXSku> getParentCodeList(List<TableXXXSku> xxxSkus, String tableName, String vbillcode) {
        List<TableXXXSku> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(xxxSkus)) {
            List<String> parentIds = xxxSkus.stream().map(TableXXXSku::getSkuParentId).distinct().collect(Collectors.toList());
            result = tableXXXSkuMapper.findAllBySkuParentIds(parentIds, tableName, vbillcode);
        }
        return result;
    }

    /**
     * 期初打印根据parentId获取父码数据
     *
     * @param xxxSkus
     * @param tableName
     * @return
     */
    private List<TableXXXSku> getQcParentCodeList(List<TableXXXSku> xxxSkus, String tableName, String vbillcode) {
        List<TableXXXSku> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(xxxSkus)) {
            List<String> parentIds = xxxSkus.stream().map(TableXXXSku::getSkuParentId).distinct().collect(Collectors.toList());
            result = tableXXXSkuMapper.findAllQcBySkuParentIds(parentIds, tableName, vbillcode);
        }
        return result;
    }

    /**
     * 插入数据并获取插入的数据
     *
     * @param vo        入参vo
     * @param tableName 表名
     * @return
     */
    private List<TableXXXSku> handleInsertTableData(PrintSkuInfoVo vo, String tableName) {
        //将入参VO的数据赋值给动态表对象
        TableXXXSku xxxSku = getTableXXXSku(vo, tableName);
        synchronized (xxxSku) {
            insertTableXXXSkuData(xxxSku);
        }
        // 查询新插入的数据
        List<TableXXXSku> listData = tableXXXSkuMapper.findListData(tableName, vo.getVbillcode(), vo.getBatchCode(), vo.getRow());
        if (Objects.nonNull(vo.getPackagingRatio())) {
            List<TableXXXSku> xxxSkus = listData.stream().filter(i -> i.getSkuPkgratio().equals("1:" + vo.getPackagingRatio())).collect(Collectors.toList());
            xxxSkus.sort(Comparator.comparing(TableXXXSku::getSortNum));
            return xxxSkus;
        }
        return listData;
    }

    @Override
    public R countPrintSkuInfo(PrintSkuInfoVo vo) {
        try {
            String tableName = "table_" + vo.getPkMaterial() + "_sku";
            PrintInfoVo printInfoVo = new PrintInfoVo();
            BigDecimal totalNum = new BigDecimal(0);
            int unPrintedNum = 0;
            int printedNum = 0;
            BigDecimal totalSkuNum = null;
            if (Objects.nonNull(vo.getNumber())) {
                totalNum = vo.getNumber().compareTo(BigDecimal.ZERO) > 0 ? vo.getNumber() : vo.getNumber().negate();
            }
            if (tableXXXSkuMapper.isTableExist(tableName)) {
                //根据批号物料主键查询动态表数据
                List<TableXXXSku> list;
                //增加判断是否是期初打印
                if(vo.getBeforePrintFlag().equals("1")){
                    String vbillcode = vo.getVbillcode().trim();
                    String substring = vbillcode.substring(0, 2);
                    list = tableXXXSkuMapper.findBeforeListData(tableName, substring, vo.getBatchCode(), vo.getRow());
                }else{
                    list= tableXXXSkuMapper.findListData(tableName, vo.getVbillcode(), vo.getBatchCode(), vo.getRow());
                }
                if (CollectionUtil.isNotEmpty(list)) {
                    if (vo.getLevel().equals("1")) {
                        List<TableXXXSku> totalList = list.stream().filter(i -> i.getCodeLevel().equals("1") && i.getSkuPkgratio().equals("1")).collect(Collectors.toList());
                        List<TableXXXSku> unPrintedList = list.stream().filter(i -> i.getPrintFlag() == 0 && i.getCodeLevel().equals("1") && i.getSkuPkgratio().equals("1")).collect(Collectors.toList());
                        if (totalList.size() != 0) {
                            unPrintedNum = unPrintedList.size();
                            printedNum = totalList.size() - unPrintedList.size();
                            totalSkuNum = totalList.stream().map(TableXXXSku::getSkuNnum).reduce(BigDecimal.ZERO,BigDecimal::add);
                        }
                    } else {
                        List<TableXXXSku> totalList = list.stream().filter(i -> !i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")).collect(Collectors.toList());
                        List<TableXXXSku> unPrintedList = totalList.stream().filter(i -> i.getPrintFlag() == 0 && !i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")).collect(Collectors.toList());
                        if (totalList.size() != 0) {
                            unPrintedNum = unPrintedList.size();
                            printedNum = totalList.size() - unPrintedList.size();
                            totalSkuNum = totalList.stream().map(TableXXXSku::getSkuNnum).reduce(BigDecimal.ZERO,BigDecimal::add);
                        }
                    }
                }
            }
            printInfoVo.setTotalNum(totalNum);
            printInfoVo.setPrintedNum(printedNum);
            printInfoVo.setUnprintedNum(unPrintedNum);
            printInfoVo.setTotalSkuNum(totalSkuNum);
            return R.ok(printInfoVo);
        } catch (Exception e) {
            return R.fail("操作失败");
        }
    }

    /**
     * 不创建一物一码时只打印一张物料标签
     * 直接将vo数据赋值给动态表对象
     *
     * @param vo
     * @return
     */
    private TableXXXSku getTableXXXSku(PrintSkuInfoVo vo, String tableName) {
        TableXXXSku xxxSku = new TableXXXSku();
        xxxSku.setPrintNum(vo.getPrintNumber());
        xxxSku.setPrintMode(vo.getPrintMode());
        xxxSku.setSortNum(vo.getSortNum());
        xxxSku.setPkMarbasclass(vo.getPkMaterial());
        xxxSku.setNum(vo.getNumber());
        xxxSku.setPkBatchcode(vo.getBatchCode());
        xxxSku.setVbatchCode(vo.getVbatchCode());
        xxxSku.setEnableState("2");
        xxxSku.setVbillcode(vo.getVbillcode());
        xxxSku.setSkuLevel(vo.getLevel());
        xxxSku.setRow(vo.getRow());
        xxxSku.setSupplierCode(vo.getSupplierCode());
        xxxSku.setDef1(vo.getDef1());
        xxxSku.setDef2(vo.getDef2());
        xxxSku.setZeroPrintList(vo.getZeroPrintList());
        if (!Objects.isNull(vo.getPackagingRatio())) xxxSku.setSkuPkgratio("1:" + vo.getPackagingRatio());
        else xxxSku.setSkuPkgratio("1");
        xxxSku.setSkuUnit(vo.getSkuUnit());
        if (StringUtils.isNotBlank(vo.getSkuNnum())) {
            xxxSku.setSkuNnum(new BigDecimal(vo.getSkuNnum()));
            xxxSku.setSkuUserNnum(new BigDecimal(vo.getSkuNnum()));
        }
        xxxSku.setFinallyCode(vo.getFinallyCode());
        xxxSku.setCreateTime(new Date());
        xxxSku.setGraphid(vo.getGraphid());
        xxxSku.setSkuState(vo.getSkuState());
        xxxSku.setPeriodValidity(DateUtils.parseDate(vo.getExpirationDate()));
        xxxSku.setResetDate(DateUtils.parseDate(vo.getResetDate()));
        xxxSku.setFlag(true);
        xxxSku.setMinUse(vo.getMinUse());
        //二级时根据批号获取最大容器号
        if (StringUtils.isNotBlank(tableName)) {
            List<TableXXXSku> dataList = tableXXXSkuMapper.findListDataByVbatchCode(tableName, vo.getVbatchCode());
            List<TableXXXSku> listData = new ArrayList<>();
            if (vo.getLevel().equals("2")) {
                if (vo.getPackagingRatio() != 0 && vo.getPackagingRatio() != null) {
                    String packageRation = "1:" + vo.getPackagingRatio();
                    listData.addAll(dataList.stream().filter(i -> i.getSkuPkgratio().equals(packageRation)).collect(Collectors.toList()));
                }
            } else {
                listData.addAll(dataList);
            }
            //根据批号过滤二级数据
            if (CollectionUtil.isNotEmpty(listData)) {
                List<TableXXXSku> collect;
                if (vo.getLevel().equals("1")) {
                    //获取一级数据
                    collect = listData.stream()
                            .filter(i -> i.getVbatchCode().equals(vo.getVbatchCode()) && i.getCodeLevel().equals("1") && i.getSkuParentId().equals("0"))
                            .collect(Collectors.toList());
                } else {
                    //获取二级数据
                    collect = listData.stream()
                            .filter(i -> i.getVbatchCode().equals(vo.getVbatchCode()) && i.getCodeLevel().equals("1") && !i.getSkuParentId().equals("0"))
                            .collect(Collectors.toList());
                }
                if (CollectionUtil.isNotEmpty(collect)) {
                    List<TableXXXSku> collect1 = collect.stream().filter(i -> Objects.nonNull(i.getSortNum()))
                            .collect(Collectors.toList());
                    List<TableXXXSku> xxxSkus = collect1.stream().sorted(Comparator.comparingInt(i -> Integer.parseInt(i.getSortNum()))).collect(Collectors.toList());
                    Integer integer = Integer.valueOf(xxxSkus.get(xxxSkus.size() - 1).getSortNum());
                    xxxSku.setMaxSortNum(integer);
                }
            }
        }
        if (StringUtils.isNotBlank(vo.getMaterialspec())) {
            xxxSku.setMaterialspec(vo.getMaterialspec());
        }
        return xxxSku;
    }

    /**
     * 拼装数据
     *
     * @param entity
     * @return
     */
    private Map<String, Object> extracted(TableXXXSku entity, String tableName) {
        synchronized (entity.getPkMarbasclass()) {
            int num = 0;
            List<TableXXXSku> batchSaveData = new ArrayList<>();
            List<TableXXXSku> batchSaveBigData = new ArrayList<>();
            //不同批号时最大容器号的初始=0
            int initNum = 0;
            String initSkuBarId = null;
            int remainingNum = 0;
            // 用于生成 sortNum 的计数器
            int sortNumCounter = 1;
            Integer initBarId = 0;
            //同批号插入数据时获取初始容器号
            List<TableXXXSku> dataList = tableXXXSkuMapper.findListDataByVbatchCode(tableName, entity.getVbatchCode());
            if (CollectionUtil.isNotEmpty(dataList)) {
                if (entity.getMaxSortNum() != 0 && Objects.nonNull(entity.getMaxSortNum())) {
                    initNum = entity.getMaxSortNum();//起始容器号
                    //根据批号获取数据
                    //根据包装比例进行获取
                    List<TableXXXSku> data = new ArrayList<>();
                    if (Objects.nonNull(entity.getSkuPkgratio())) {
                        data.addAll(dataList.stream().filter(i -> i.getSkuPkgratio().equals(entity.getSkuPkgratio()))
                                .collect(Collectors.toList()));
                    } else {
                        data.addAll(dataList);
                    }
                    if (entity.getSkuLevel().equals("2")) {
                        //根据容器号删除
                        if (StringUtils.isNotBlank(entity.getSortNum())) {
                            List<TableXXXSku> deleteSortNum = data.stream().filter(i -> !i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")
                                            && !i.getSkuPkgratio().equals("1") && Integer.parseInt(i.getSortNum()) > Integer.parseInt(entity.getSortNum()))
                                    .collect(Collectors.toList());
                            List<Integer> deleteList = deleteSortNum.stream().map(TableXXXSku::getId).collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(deleteList)) {
                                //获取父码数据一并删除
//                        List<TableXXXSku> parentCodeList = getParentCodeList(deleteSortNum, tableName, entity.getVbillcode());
//                        deleteList.addAll(parentCodeList.stream().map(TableXXXSku::getId).collect(Collectors.toList()));
                                tableXXXSkuMapper.deleteXXXSkuByIdList(tableName, deleteList);
                            }
                            data.removeAll(deleteSortNum);
                            List<TableXXXSku> skuList = data.stream().sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).collect(Collectors.toList());
                            initNum = Integer.parseInt(entity.getSortNum());

                            if (CollectionUtil.isNotEmpty(skuList)) {
                                TableXXXSku tableXXXSku = skuList.get(0);
                                num = Integer.parseInt(tableXXXSku.getSkuBarId().substring(1).replaceFirst("^0+", ""));
                            }
                        }
                        int pkNum = Integer.parseInt(entity.getSkuPkgratio().split(":")[1]);
                        //小码数据
                        List<TableXXXSku> oneLevelList = data.stream().filter(i -> !i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")).collect(Collectors.toList());
                        //大码数据
                        List<TableXXXSku> twoLevelList = data.stream().filter(i -> i.getSkuParentId().equals("0") && i.getCodeLevel().equals("2")).collect(Collectors.toList());
                        //获取最大容器号
                        List<Integer> sortList = new ArrayList<>();
                        twoLevelList.forEach(e -> {
                            int index = e.getSortNum().indexOf("/") + 1;
                            sortList.add(Integer.valueOf(e.getSortNum().substring(index)));
                        });
                        //尾箱的最大序列号
                        Integer max = CollectionUtil.max(sortList);
                        //尾箱未装满情况
                        if (oneLevelList.size() < max) {
                            //包装比例
                            //最后一箱的空余数量
                            remainingNum = max - oneLevelList.size();
                        }
                        int i = max - pkNum + 1;
                        //获取最后一个大码数据
                        Integer finalMax = max;
                        //根据尾箱包装比例获取最后一个大码数据
                        List<TableXXXSku> collect = twoLevelList.stream().filter(item -> item.getSortNum().equals(String.format("%03d", i) + "/" + String.format("%03d", (finalMax)))).collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(collect)) {
                            TableXXXSku xxxSku = collect.get(0);
                            //最后一个大码的skubarid
                            initSkuBarId = xxxSku.getSkuBarId();
                            String skuBarId = xxxSku.getSkuBarId();
                            //截取掉第一位
                            String substring = skuBarId.substring(1);
                            //修改起始容器号
                            Integer integer = Integer.valueOf(substring.replaceFirst("^0+", ""));
                            num = integer;
                            List<TableXXXSku> oneList = oneLevelList.stream().sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).collect(Collectors.toList());
                            TableXXXSku tableXXXSku = oneList.get(0);
                            initBarId = Integer.valueOf(tableXXXSku.getSkuBarId().substring(1).replaceFirst("^0+", ""));
                        }
                        sortNumCounter = ++max;
                    } else {
                        List<TableXXXSku> skuList = new ArrayList<>();
                        if (entity.getPrintMode().equals("0")) {
                            int initSortNum;
                            if (StringUtils.isBlank(entity.getSortNum())) {
                                initSortNum = initNum;
                            } else {
                                initSortNum = Integer.parseInt(entity.getSortNum());
                            }
                            int finalInitSortNum = initSortNum;
                            List<TableXXXSku> deleteSortNum = data.stream().filter(i -> i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")
                                            && i.getSkuPkgratio().equals("1") && Integer.parseInt(i.getSortNum()) > finalInitSortNum)
                                    .collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(deleteSortNum)) {
                                List<Integer> deleteList = deleteSortNum.stream().map(TableXXXSku::getId).collect(Collectors.toList());
                                tableXXXSkuMapper.deleteXXXSkuByIdList(tableName, deleteList);
                                data.removeAll(deleteSortNum);
                            }
                            skuList = data.stream().sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).collect(Collectors.toList());
                        } else {
                            skuList = data.stream().filter(i -> i.getSkuParentId().equals("0") && i.getCodeLevel().equals("1")
                                    && i.getSkuPkgratio().equals("1")).sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).collect(Collectors.toList());
                        }
                        if (CollectionUtil.isNotEmpty(skuList)) {
                            TableXXXSku tableXXXSku = skuList.get(0);
                            num = Integer.parseInt(tableXXXSku.getSkuBarId().substring(1).replaceFirst("^0+", ""));
                        }
                    }
                }
                List<TableXXXSku> twoLevelList = dataList.stream().filter(i -> i.getSkuParentId().equals("0") && i.getCodeLevel().equals("2")).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(twoLevelList)) {
                    List<TableXXXSku> skuList = twoLevelList.stream().sorted(Comparator.comparing(TableXXXSku::getSkuBarId).reversed()).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(skuList)) {
                        TableXXXSku tableXXXSku = skuList.get(0);
                        num = Integer.parseInt(tableXXXSku.getSkuBarId().substring(1).replaceFirst("^0+", ""));

                    }
                }
            }

            //总数为打印数量
            Integer totalNum = entity.getPrintNum();
            if (remainingNum > 0 && totalNum != 1) {
                totalNum = Math.max(totalNum - remainingNum, 0); // 避免负数
            }
            //打印数量为1时，尾箱剩余数量大于0
            if (totalNum == 1 && remainingNum > 0) {
                remainingNum = 1;
            }
            if (entity.getSkuLevel().equals("2")) {
                //填充最后一箱逻辑
                if (initSkuBarId != null) {
                    for (int k = 1; k <= remainingNum; k++) {
                        TableXXXSku temp = new TableXXXSku();
                        BeanUtils.copyProperties(entity, temp);
                        temp.setSkuLevel("1");
                        String newString = "1" + String.format("%012d", (++initBarId));
                        temp.setSkuBarId(newString);
                        temp.setSkuParentId(initSkuBarId);
                        temp.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                        temp.setEnableState("2");
                        temp.setSkuState("2");
                        temp.setSkuLevel("1");
                        temp.setUnixTime(String.valueOf(System.currentTimeMillis()));
                        temp.setDef5(null);
                        //二级包装设置容器号
                        temp.setSortNum(String.format("%03d", (++initNum)));
                        temp.setCodeLevel("1");
                        temp.setPrintFlag(1);
                        temp.setGubflag("1");//整箱、零箱标识：1整箱 0 零箱
                        batchSaveData.add(temp);
                    }
                }
                int pkNum = Integer.parseInt(entity.getSkuPkgratio().split(":")[1]);
                //判断剩余的总数是否大于包装比例的数据
                int cycleNum = totalNum / pkNum;//求商
                int reNum = totalNum % pkNum;//求余
                if (reNum > 0 && cycleNum != 0) {
                    ++cycleNum;
                }
                if (entity.getPrintNum() == remainingNum) {
                    cycleNum = 0;
                }else{
                    //根据商数和余数去判断是否需要生成大码
                    if (cycleNum == 0 && reNum != 0) {
                        cycleNum = 1;
                    }
                }
                int towCycleNum = 0;
                //正常二级数据生成逻辑
                for (int i = 0; i < cycleNum; i++) {
                    TableXXXSku xxxSku = new TableXXXSku();
                    BeanUtils.copyProperties(entity, xxxSku);
                    //生成SN码，SN码为商品追溯码唯一标识
                    int num1 = ++num;
                    String newString = entity.getSkuLevel() + String.format("%012d", (num1));
                    xxxSku.setSkuBarId(newString);
                    xxxSku.setSkuParentId("0");
                    xxxSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                    xxxSku.setEnableState("2");
                    xxxSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                    xxxSku.setSkuState("2");
                    xxxSku.setCodeLevel("2");
                    xxxSku.setSkuLevel("2");
                    xxxSku.setGubflag("1");//整箱、零箱标识：1整箱 0 零箱
                    if (xxxSku.getSkuLevel().equals("2")) {
                        xxxSku.setSkuPkgratio("1:" + pkNum);
                    } else {
                        xxxSku.setSkuPkgratio("");
                    }
                    String sortNum;//大码容器号：格式：001/002
                    if (cycleNum == 1) {
                        sortNum = String.format("%03d", (sortNumCounter)) + "/" + String.format("%03d", ((sortNumCounter + pkNum - 1)));
                        towCycleNum = totalNum;
                    } else {
                        sortNum = String.format("%03d", (sortNumCounter)) + "/" + String.format("%03d", ((sortNumCounter + pkNum - 1)));
                        towCycleNum = pkNum;
                        sortNumCounter += pkNum;
                    }
                    //填充尾箱时不生成大码
                    if (entity.getPrintNum()> remainingNum) {
                        xxxSku.setSortNum(sortNum);
                        xxxSku.setPrintFlag(1);
                        batchSaveBigData.add(xxxSku);
                    }
                    int minCode = 0;
                    int twoNum = totalNum + cycleNum;
                    if(Objects.equals(entity.getPrintNum(), totalNum)){
                        twoNum = totalNum;
                    }
                    for (int j = 0; j < towCycleNum && batchSaveData.size() < twoNum; j++) {
                        TableXXXSku tableXXXSku = new TableXXXSku();
                        BeanUtils.copyProperties(entity, tableXXXSku);
                        //生成SN码，SN码为商品追溯码唯一标识
                        /**
                         * SN码生成规则：父码+子码序列号
                         * 父码第一位为级别后续为0，子码默认从0000001开始
                         */
                        String newString1 = "1" + String.format("%06d", num);
                        String newString2 = newString1 + String.format("%06d", ++minCode);
                        tableXXXSku.setSkuBarId(newString2);
                        tableXXXSku.setSkuParentId(xxxSku.getSkuBarId());
                        tableXXXSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                        tableXXXSku.setEnableState("2");
                        tableXXXSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                        tableXXXSku.setSkuState("2");
                        tableXXXSku.setSkuLevel("1");
                        tableXXXSku.setCodeLevel("1");
                        tableXXXSku.setPrintFlag(1);
                        tableXXXSku.setGubflag("1");//整箱、零箱标识：1整箱 0 零箱
                        tableXXXSku.setSortNum(String.format("%03d", (++initNum)));
                        batchSaveData.add(tableXXXSku);
                    }
                }
                //拆零逻辑处理
                List<PrintZeroSkuInfoVo> zeroPrintList = entity.getZeroPrintList();
                if(CollectionUtil.isNotEmpty(zeroPrintList)){
                    int zeroInitNum = 0;
                    if(initNum!=0){
                        zeroInitNum = initNum;
                    }
                    for (int i = 0; i < 1; i++) {
                        TableXXXSku xxxSku = new TableXXXSku();
                        BeanUtils.copyProperties(entity, xxxSku);
                        //生成SN码，SN码为商品追溯码唯一标识
                        int num1 = ++num;
                        String newString = entity.getSkuLevel() + String.format("%012d", (num1));
                        xxxSku.setSkuBarId(newString);
                        xxxSku.setSkuParentId("0");
                        xxxSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                        xxxSku.setEnableState("2");
                        xxxSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                        xxxSku.setSkuState("2");
                        xxxSku.setCodeLevel("2");
                        xxxSku.setSkuLevel("2");
                        xxxSku.setSkuPkgratio("1:" + pkNum);
                        String sortNum = String.format("%03d", (++zeroInitNum)) + "/" + String.format("%03d", ((zeroInitNum + zeroPrintList.size()-1)));
                        xxxSku.setSortNum(sortNum);
                        xxxSku.setPrintFlag(1);
                        xxxSku.setGubflag("0");//整箱、零箱标识：1整箱 0 零箱
                        batchSaveData.add(xxxSku);
                        int zeroCode = 0;
                        for (PrintZeroSkuInfoVo skuInfoVo : zeroPrintList) {
                            TableXXXSku tableXXXSku = new TableXXXSku();
                            BeanUtils.copyProperties(entity, tableXXXSku);
                            BigDecimal bigDecimal = new BigDecimal(skuInfoVo.getSkuNnum());
                            tableXXXSku.setSkuNnum(bigDecimal);
                            tableXXXSku.setSkuUserNnum(bigDecimal);
                            //生成SN码，SN码为商品追溯码唯一标识
                            /**
                             * SN码生成规则：父码+子码序列号
                             * 父码第一位为级别后续为0，子码默认从0000001开始
                             */
                            String newString1 = "1" + String.format("%06d", num);
                            String newString2 = newString1 + String.format("%06d", ++zeroCode);
                            tableXXXSku.setSkuBarId(newString2);
                            tableXXXSku.setSkuParentId(xxxSku.getSkuBarId());
                            tableXXXSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                            tableXXXSku.setEnableState("2");
                            tableXXXSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                            tableXXXSku.setSkuState("2");
                            tableXXXSku.setSkuLevel("1");
                            tableXXXSku.setCodeLevel("1");
                            tableXXXSku.setPrintFlag(1);
                            tableXXXSku.setSortNum(String.format("%03d", (++initNum)));
                            tableXXXSku.setGubflag("0");//整箱、零箱标识：1整箱 0 零箱
                            batchSaveData.add(tableXXXSku);
                        }
                    }
                }
            } else {
                //先走正常逻辑
                for (int i = 0; i < totalNum; i++) {
                    TableXXXSku xxxSku = new TableXXXSku();
                    BeanUtils.copyProperties(entity, xxxSku);
                    //生成SN码，SN码为商品追溯码唯一标识
                    /**
                     * SN码生成规则：父码+子码序列号
                     * 父码第一位为级别后续为0，子码默认从0000001开始
                     */
                    String newString = entity.getSkuLevel() + String.format("%012d", (++num));
                    xxxSku.setSkuBarId(newString);
                    xxxSku.setSkuParentId("0");
                    xxxSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                    xxxSku.setEnableState("2");
                    xxxSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                    xxxSku.setSkuState("2");
                    xxxSku.setCodeLevel("1");
                    xxxSku.setPrintFlag(1);
                    xxxSku.setSortNum(String.format("%03d", (++initNum)));
                    xxxSku.setGubflag("1");//整箱、零箱标识：1整箱 0 零箱
                    batchSaveData.add(xxxSku);
                }
                //若存在零箱，则执行拆零逻辑
                List<PrintZeroSkuInfoVo> zeroPrintList = entity.getZeroPrintList();
                if(CollectionUtil.isNotEmpty(zeroPrintList)){
                    for (PrintZeroSkuInfoVo infoVo : zeroPrintList) {
                        for (int i = 0; i < 1; i++) {
                            TableXXXSku xxxSku = new TableXXXSku();
                            BeanUtils.copyProperties(entity, xxxSku);
                            //对零箱最小使用数量进行赋值
                            BigDecimal bigDecimal = new BigDecimal(infoVo.getSkuNnum());
                            xxxSku.setSkuNnum(bigDecimal);
                            xxxSku.setSkuUserNnum(bigDecimal);
                            //生成SN码，SN码为商品追溯码唯一标识
                            /**
                             * SN码生成规则：父码+子码序列号
                             * 父码第一位为级别后续为0，子码默认从0000001开始
                             */
                            String newString = entity.getSkuLevel() + String.format("%012d", (++num));
                            xxxSku.setSkuBarId(newString);
                            xxxSku.setSkuParentId("0");
                            xxxSku.setCreator(SecurityUtils.getLoginUser().getUser().getUserName());
                            xxxSku.setEnableState("2");
                            xxxSku.setUnixTime(String.valueOf(System.currentTimeMillis()));
                            xxxSku.setSkuState("2");
                            xxxSku.setCodeLevel("1");
                            xxxSku.setPrintFlag(1);
                            xxxSku.setSortNum(String.format("%03d", (++initNum)));
                            xxxSku.setGubflag("0");//整箱、零箱标识：1整箱 0 零箱
                            batchSaveData.add(xxxSku);
                        }
                    }
                }
            }
            Map<String, Object> map = new HashMap<>();
            if(CollectionUtil.isNotEmpty(batchSaveBigData)){
                batchSaveData.addAll(batchSaveBigData);
            }
            map.put("num", num);
            map.put("data", batchSaveData);
            return map;
        }
    }

    /**
     * 创建防御性处理的VO对象
     * @param original 原始对象
     * @return 处理后的对象
     */
    private PrintSkuInfoVo createProcessedVo(PrintSkuInfoVo original) {
        PrintSkuInfoVo copy = new PrintSkuInfoVo();
        BeanUtils.copyProperties(original, copy);
        return copy;
    }

    /**
     * 数据组装，将vo对象的数据赋给数组中的每一个对象
     *
     * @param xxxSkuList
     * @param skuVo1List
     * @param vo
     * @return
     */
    private List<PrintSkuInfoVo> dataAssembly(List<TableXXXSku> xxxSkuList,
                                              List<TableXXXSkuVo1> skuVo1List,
                                              PrintSkuInfoVo vo) {
        // 创建防御性副本避免修改原始对象
        PrintSkuInfoVo processedVo = createProcessedVo(vo);

        // 统一处理日期格式化
        processDateFields(processedVo);

        // 应用业务规则
        applyBusinessRules(processedVo);

        // 合并处理两个列表
        List<PrintSkuInfoVo> printSkuInfoVos = Stream.concat(
                processSkuList(xxxSkuList, processedVo, false),
                processSkuList(skuVo1List, processedVo, true)
        ).collect(Collectors.toList());
        //复验期为1900-01-01时返回N/A
        printSkuInfoVos.forEach(i -> {
            if (Objects.nonNull(i.getResetDate()) && i.getResetDate().equals("1900-01-01")) {
                i.setResetDate("N/A");
            }
        });
        return printSkuInfoVos;
    }

    /**
     * 处理日期字段
     * @param vo 模板对象
     */
    private void processDateFields(PrintSkuInfoVo vo) {
        vo.setResetDate(formatDate(vo.getResetDate()));
        vo.setExpirationDate(formatDate(vo.getExpirationDate()));
        vo.setProductionDate(formatDate(vo.getProductionDate()));
    }

    /**
     * 格式化日期字段
     * @param dateStr 日期字段
     * @return 日期
     */
    private String formatDate(String dateStr) {
        if (StringUtils.isBlank(dateStr)) return dateStr;

        Date date = DateUtils.parseDate(dateStr);
        return new SimpleDateFormat(DATE_PATTERN).format(date);
    }

    /**
     * 应用业务规则
     * @param vo 打印模版对象
     */
    private void applyBusinessRules(PrintSkuInfoVo vo) {
        boolean hasProduction = StringUtils.isNotBlank(vo.getProductionDate());
        boolean hasExpiration = StringUtils.isNotBlank(vo.getExpirationDate());
        boolean hasReset = StringUtils.isNotBlank(vo.getResetDate());

        // 规则优先级：复验期存在时优先处理
        if (hasReset && !vo.getResetDate().equals("1900-01-01")) {
            vo.setExpirationDate(NA_VALUE);
        } else if (hasExpiration) {
            vo.setResetDate(NA_VALUE);
        }

        // 特殊场景处理：当生产日期存在但无有效/复验期时
        if (hasProduction && !hasExpiration && !hasReset) {
            vo.setResetDate(NA_VALUE);
            vo.setExpirationDate(NA_VALUE);
        }
    }

    private Stream<PrintSkuInfoVo> processSkuList(List<?> skuList,
                                                  PrintSkuInfoVo templateVo,
                                                  boolean isVo1Type) {
        if (CollectionUtils.isEmpty(skuList)) return Stream.empty();

        return skuList.stream().map(sku -> {
            PrintSkuInfoVo vo = new PrintSkuInfoVo();
            BeanUtils.copyProperties(templateVo, vo);

            if (sku instanceof TableXXXSku) {
                TableXXXSku s = (TableXXXSku) sku;
                vo.setQRCode(s.getQRCode());
                vo.setSkuBarId(s.getSkuBarId());
                vo.setGubflag(s.getGubflag());
                vo.setDef2(s.getDef2());
            } else if (sku instanceof TableXXXSkuVo1) {
                TableXXXSkuVo1 s = (TableXXXSkuVo1) sku;
                vo.setQRCode(s.getQRCode());
                vo.setSkuBarId(s.getSkuBarId());
                vo.setGubflag(s.getGubflag());
                vo.setDef2(s.getDef2());
                if (isVo1Type) vo.setSortNum(s.getSortNum());
            }
            return vo;
        });
    }

    /**
     * 递归获取当前父类及其子对象
     *
     * @param skuList 数据存在时的数据
     */
    private List<TableXXXSku> printedData(List<TableXXXSku> skuList, List<TableXXXSku> resultList, String parentId) {
        if (CollectionUtil.isNotEmpty(skuList)) {
            resultList.addAll(skuList.stream()
                    .filter(sku -> (StringUtils.isNotBlank(sku.getSkuParentId()) && sku.getSkuParentId().equals(parentId)) || sku.getSkuBarId().equals(parentId))
                    .collect(Collectors.toList()));
        }
        return resultList;
    }
}




